package com.regent.central.bill.web.delivery;

import com.regent.central.bill.common.ActionType;
import com.regent.central.bill.common.ChangeType;
import com.regent.central.bill.core.*;
import com.regent.central.bill.core.storehouse.StockChange;
import com.regent.central.bill.core.storehouse.StockChangeSku;
import com.regent.central.bill.core.storehouse.StockInventoryItemSku;
import com.regent.central.bill.dto.delivery.*;
import com.regent.central.bill.dto.storehouse.ChangeNoAndNewDateDTO;
import com.regent.central.bill.service.*;
import com.regent.central.bill.service.storehouse.*;
import com.regent.central.infrastructure.common.TimeKit;
import com.regent.central.infrastructure.common.Uid;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 发货控制器
 *
 * @author 杨昌沛 646742615@qq.com
 * @date 2018-06-21 10:21
 **/
@Controller
@RequestMapping("/delivery")
public class DeliveryController {

    @Resource
    private SaleOrderService saleOrderService;

    @Resource
    private SaleOrderActionService saleOrderActionService;

    @Resource
    private DeliveryGoodsService deliveryGoodsService;

    @Resource
    private DeliveryGoodsSKUService deliveryGoodsSKUService;

    @Resource
    private DeliveryOrderService deliveryOrderService;

    @Resource
    private DeliveryActionService deliveryActionService;

    @Resource
    private StockSkuService stockSkuService;

    @Resource
    private StockStyleService stockStyleService;

    @Resource
    private StockChangeService stockChangeService;

    @Resource
    private StockChangeSkuService stockChangeSkuService;

    @Resource
    private StockInventoryItemSkuService stockInventoryItemSkuService;

    @Resource
    private StockInventoryItemService stockInventoryItemService;

    /**
     * 发货-客户销售单列表API
     *
     * @param request 请求参数
     * @return 该组织的该客户所有还没发货的销售单列表
     */
    @RequestMapping(value = "/sale/orders", method = RequestMethod.GET)
    @ResponseBody
    public DeliverySaleOrdersResponse getSaleOrders(
            DeliverySaleOrdersRequest request
    ) {
        List<DeliverySaleOrderDTO> owedSaleOrders = saleOrderService.getOwedSaleOrders(
                request.getUnitId(),
                request.getCustomerId(),
                request.getStartSearchTime(),
                request.getStartTime(),
                request.getEndTime(),
                request.getType(),
                request.getSort(),
                request.getKeyword(),
                request.getPageNo(),
                request.getPageSize()
        );

        DeliverySaleOrdersResponse response = new DeliverySaleOrdersResponse();
        response.setOrders(owedSaleOrders);
        return response;
    }

    /**
     * 发货
     *
     * @param request 发货请求
     * @return 发货结果
     */
    @RequestMapping(value = "/sale/orders", method = RequestMethod.POST)
    @ResponseBody
    public DeliverySendResponse send(
            @RequestBody DeliverySendRequest request
    ) {
        DeliverySendResponse response = new DeliverySendResponse();

        List<String> ids = saleOrderService.doAtomically(() -> {
            if (StringUtils.isNotBlank(request.getDeliveryOrderId())){
                deliveryOrderService.revoke(request.getDeliveryOrderId(),request.getUserId());
            }
            return  saveDeliveryGoods(request);
        });
        if (ids == null||ids.size()==0) {
            response = new DeliverySendResponse();
            response.setCode(500);
            response.setMessage("发货失败");
            return response;
        } else {
            response.setDeliveryOrderIds(ids);
            return response;
        }
    }

    private List<String> saveDeliveryGoods(DeliverySendRequest request) {
        List<String> orderIds = new ArrayList<>();

        String storehouseId = request.getStorehouseId();
        String userId = request.getUserId();
        //String unitId = request.getUnitId();

        List<DeliverySendCustDTO> custList = request.getCustList();
        if (custList == null || custList.isEmpty()) return null;

        String deliveryDay = request.getDeliveryDay();
        boolean insertFlag = false;
        if (deliveryDay == null) {
            deliveryDay = TimeKit.format(new Date(), "yyyy-MM-dd");
            insertFlag = true;
        }
        //变动记录编号
        ChangeNoAndNewDateDTO maxChangeNoAndNewDate = stockChangeService.getMaxChangeNoAndNewDate(storehouseId, deliveryDay);
        Date newTime = maxChangeNoAndNewDate.getNewTime();
        int changeNo = maxChangeNoAndNewDate.getNo();

        //发货单号
        Integer maxDeliveryNo = deliveryOrderService.getMaxDeliveryNoByDate(request.getUnitId(), deliveryDay);
        Integer deliveryNo = maxDeliveryNo == null ? 1 : maxDeliveryNo + 1;

        for (DeliverySendCustDTO cust : custList) {
            //Date newDate = null;
            BigDecimal totalDelivered = new BigDecimal("0");

            Set<String> styleIds = new HashSet<>();

            Delivery delivery = new Delivery();
            delivery.setId(Uid.random());
            delivery.setBossUnitId(request.getBossUnitId());
            delivery.setUnitId(request.getUnitId());
            delivery.setCustomerId(cust.getCustId());
            delivery.setDeliveryDay(deliveryDay);
            //单号
            delivery.setDeliveryNo(deliveryNo + "");
            //时间
            delivery.setDateDelivered(newTime);
            delivery.setDelivererId(request.getUserId());
            delivery.setUserCreated(request.getUserId());


            List<DeliverySendOrderDTO> orders = cust.getOrders();
            if (orders==null||orders.size()==0){
                return null;
            }
            for (DeliverySendOrderDTO orderDTO : orders) {
                if (orderDTO.getStyles() == null || orderDTO.getStyles().isEmpty()) return null;

                BigDecimal stockCount = new BigDecimal(0);

                //添加库存变动记录
                StockChange stockChange = new StockChange();
                String uuid = Uid.random();
                stockChange.setId(uuid);
                stockChange.setBossUnitId(request.getBossUnitId());
                stockChange.setUnitId(request.getUnitId());
                stockChange.setCreateBy(request.getUserId());
                stockChange.setInventoryType(ChangeType.DELIVER.getType());
                stockChange.setStorehouseId(request.getStorehouseId());
                stockChange.setOpBy(request.getUserId());

                // 保存销售单的发货单操作记录
                SaleOrderAction parent = new SaleOrderAction();
                parent.setId(Uid.random());
                parent.setUserCreated(request.getUserId());
                parent.setCentralBillSaleOrderId(orderDTO.getSaleOrderId());
                parent.setActionType(ActionType.DELIVERY);
                parent.setActionId(delivery.getId());
                parent.setUserCreated(request.getUserId());
                saleOrderActionService.insertSelective(parent);

                for (DeliverySendStyleDTO styleDTO : orderDTO.getStyles()) {
                    DeliveryGoods goods = new DeliveryGoods();
                    goods.setId(Uid.random());
                    goods.setBossUnitId(request.getBossUnitId());
                    goods.setUnitId(request.getUnitId());
                    goods.setUserCreated(request.getUserId());
                    goods.setGoodsId(styleDTO.getGoodsId());
                    goods.setStyleId(styleDTO.getStyleId());

                    styleIds.add(styleDTO.getStyleId());

                    deliveryGoodsService.insertSelective(goods);

                    SaleOrderAction action = new SaleOrderAction();
                    action.setId(Uid.random());
                    action.setParentId(parent.getId());
                    action.setUserCreated(request.getUserId());
                    action.setCentralBillSaleOrderId(orderDTO.getSaleOrderId());
                    action.setActionType(ActionType.DELIVERY_GOODS);
                    action.setActionId(goods.getId());
                    saleOrderActionService.insertSelective(action);

                    DeliveryAction deliveryAction = new DeliveryAction();
                    deliveryAction.setId(Uid.random());
                    deliveryAction.setActionType(ActionType.DELIVERY_GOODS);
                    deliveryAction.setActionId(goods.getId());
                    deliveryAction.setCentralBillDeliveryId(delivery.getId());
                    deliveryAction.setUserCreated(request.getUserId());

                    deliveryActionService.insertSelective(deliveryAction);


                    List<DeliverySendStyleSKUDTO> skus = styleDTO.getSkus();
                    //BigDecimal totalSkus = new BigDecimal("0");
                    //saveDeliveryGoodsSkus(request, goods.getId(), skus, totalSkus,insertFlag);

                    if (skus == null || skus.isEmpty()) return null;

                    StockInventoryItemSku stockInventoryItemSku = null;

                    for (DeliverySendStyleSKUDTO dto : skus) {
                        DeliveryGoodsSKU sku = new DeliveryGoodsSKU();
                        sku.setId(Uid.random());
                        sku.setCentralActionDeliveryGoodsId(goods.getId());
                        sku.setSkuId(dto.getSkuId());
                        sku.setQuantity(dto.getQuantity());
                        sku.setUserCreated(request.getUserId());
                        sku.setPrice(dto.getPrice() == null ? BigDecimal.ZERO : dto.getPrice());
                        //TODO
                        deliveryGoodsSKUService.insertSelective(sku);
                        stockCount = stockCount.add(dto.getQuantity());

                        BigDecimal stock = new BigDecimal("0").subtract(dto.getQuantity());

                        //新增货品库存变动记录详情
                        StockChangeSku stockChangeSku = new StockChangeSku();
                        stockChangeSku.setId(Uid.random());
                        stockChangeSku.setStorehouseId(storehouseId);
                        stockChangeSku.setTargetId(styleDTO.getStyleId());
                        stockChangeSku.setTargetType("COMMON_GOODS_STYLE");
                        stockChangeSku.setGoodsUnitId(styleDTO.getGoodsId());
                        stockChangeSku.setNum(stock);
                        stockChangeSku.setSkuId(dto.getSkuId());
                        stockChangeSku.setStockChangeId(uuid);
                        stockChangeSku.setOpBy(userId);

                        Boolean changeType = false;
                        if (insertFlag)
                       /* {
                            //减库存
                            //log.info("减sku库存，skuId:{},storehouseId：{},变动数：{}", skuId, storehouseId, stock);
                            stockSkuService.updateStock(dto.getSkuId(), storehouseId, stock);
                            //log.info("减货品库存，goodsId:{},storehouseId：{},变动数：{}", goodsId, storehouseId, stock);
                            stockStyleService.updateStock(styleDTO.getGoodsId(), storehouseId, stock);
                        } else*/ {
                            stockInventoryItemSku = new StockInventoryItemSku();
                            stockInventoryItemSku.setDelFlag(false);
                            //盘点sku
                            stockInventoryItemSku.setSkuId(dto.getSkuId());
                            //获取该时间后有sku变动的盘点id
                            Map<String, Object> inventory = stockChangeSkuService.selectInventoryId(dto.getSkuId(), storehouseId, newTime);
                            //要变动的盘点ids
                            List<String> inventoryIds = null;
                            if (inventory != null) {
                                String inventoryId = (String) inventory.get("inventoryId");
                                Date inventoryTime = (Date) inventory.get("inventoryTime");

                                //获取 newTime 与 inventoryTime 内的已撤销或未调整盘点id
                                inventoryIds = stockInventoryItemSkuService.selectNoAdjustInventoryId(dto.getSkuId(), storehouseId, newTime, inventoryTime);
                                //加入要变动inventoryId
                                inventoryIds.add(inventoryId);

                                //变动类型
                                changeType = true;
                            } else {
                                //获取时间后已撤销或未调整的盘点
                                inventoryIds = stockInventoryItemSkuService.selectNoAdjustInventoryId(dto.getSkuId(), storehouseId, newTime, null);
                            }
                            //盘点ids
                            if (inventoryIds != null && inventoryIds.size() > 0) {
                                for (String id : inventoryIds) {
                                    stockInventoryItemSku.setStockInventoryId(id);
                                    //判断该sku是否存在盘点单中
                                    List<StockInventoryItemSku> stockInventoryItemSkus = stockInventoryItemSkuService.selectList(stockInventoryItemSku);
                                    if (stockInventoryItemSkus != null && stockInventoryItemSkus.size() > 0) {
                                        //累加款盘点的账面库存
                                        //log.info("累加款盘点的账面库存,styleId:{},inventoryId:{},变动数:{}", styleId, id, stock);
                                        stockInventoryItemService.updateBookStock(styleDTO.getStyleId(), id, stock);
                                        //累加sku盘点的账面库存
                                        //log.info("累加sku盘点的账面库存,skuId:{},inventoryId:{},变动数:{}", skuId, id, stock);
                                        stockInventoryItemSkuService.updateBookStock(dto.getSkuId(), id, stock);
                                        //更新调整记录 累加
                                        //log.info("更新调整记录,skuId:{},inventoryId:{},变动数:{},userId:{}", skuId, id, oppNum, userId);
                                        stockChangeSkuService.updateChangeNum(dto.getSkuId(), id, dto.getQuantity(), userId);
                                    }
                                }
                            }

                            if (!changeType) {
                                //减sku实时库存
                                //log.info("累加sku实时库存,skuId:{},storehouseId:{},变动数:{}", skuId, storehouseId, stock);
                                stockSkuService.updateStock(dto.getSkuId(), storehouseId, stock);
                                //减货品实时库存
                                // log.info("累加货品实时库存,goodsId:{},storehouseId:{},变动数:{}", goodsId, storehouseId, stock);
                                stockStyleService.updateStock(styleDTO.getGoodsId(), storehouseId, stock);

                                //TODO 欠货
                            }
                        }
                        //插入sku变动记录
                        //log.info("插入sku变动记录");
                        stockChangeSku.setChangeType(changeType);
                        stockChangeSkuService.insertSelective(stockChangeSku);

                    }
                }
                totalDelivered = totalDelivered.add(stockCount);
                stockChange.setInventoryTime(newTime);
                stockChange.setInventoryNo(changeNo++);
                stockChange.setNum(new BigDecimal("0").subtract(stockCount));
                stockChange.setSubtractNum(stockChange.getNum());
                //插入变动记录
                //log.info("插入变动记录");
                stockChangeService.insertSelective(stockChange);

            }
            delivery.setStyleCount(styleIds.size());
            delivery.setTotalDelivered(totalDelivered);
            deliveryOrderService.insertSelective(delivery);
            orderIds.add(delivery.getId());
        }


        return orderIds;
    }

   /* private void saveDeliveryGoodsSkus(DeliverySendRequest request, String deliveryGoodsId, List<DeliverySendStyleSKUDTO> skus, BigDecimal totalSkus, boolean insertFlag) {
        if (skus == null || skus.isEmpty()) return;

        for (DeliverySendStyleSKUDTO dto : skus) {
            DeliveryGoodsSKU sku = new DeliveryGoodsSKU();
            sku.setId(Uid.random());
            sku.setCentralActionDeliveryGoodsId(deliveryGoodsId);
            sku.setSkuId(dto.getSkuId());
            sku.setQuantity(dto.getQuantity());
            sku.setUserCreated(request.getUserId());
            deliveryGoodsSKUService.insertSelective(sku);
            totalSkus = totalSkus.add(dto.getQuantity());
        }
    }*/

    @RequestMapping(value = "/find/delivered", method = RequestMethod.GET)
    @ResponseBody
    public DeliveryFindResponse findIsDelivery(@RequestParam("unitId") String unitId, @RequestParam("styleId") String styleId) throws Exception {
        DeliveryFindResponse response = new DeliveryFindResponse();
        boolean isDelivery = deliveryGoodsService.isDeliveryGoods(unitId, styleId);
        response.setDelivery(isDelivery);
        return response;
    }

    /**
     * 发货单列表API
     *
     * @param request 请求参数
     * @return 发货单列表
     */
    @RequestMapping(value = "/orders", method = RequestMethod.GET)
    @ResponseBody
    public DeliveryOrderResponse getDeliveryOrders(
            DeliveryOrderRequest request
    ) {
        List<DeliveryOrderDTO> deliveryOrder = deliveryOrderService.getDeliveryOrder(
                request.getUnitId(),
                request.getKeyword(),
                request.getEmpIds(),
                request.getStartSearchTime(),
                request.getStartTime(),
                request.getEndTime(),
                request.getPageNo(),
                request.getPageSize()
        );

        DeliveryOrderResponse response = new DeliveryOrderResponse();
        response.setDeliveryOrders(deliveryOrder);
        return response;
    }

    /**
     * 发货单详情API
     *
     * @param deliveryOrderId 请求参数
     * @return 发货单详情
     */
    @RequestMapping(value = "/orders/detail", method = RequestMethod.GET)
    @ResponseBody
    public DeliveryOrderDetailResponse getDeliveryOrdersDetail(
            @RequestParam("deliveryOrderId") String deliveryOrderId
    ) {
        DeliveryDetailDTO detail = deliveryOrderService.getDeliveryOrderDetail(
                deliveryOrderId
        );

        DeliveryOrderDetailResponse response = new DeliveryOrderDetailResponse();
        response.setDetail(detail);
        return response;
    }

    /**
     * 发货单操作记录
     *
     * @param deliveryOrderId
     * @return
     */
    @RequestMapping(value = "/orders/record", method = RequestMethod.GET)
    @ResponseBody
    public DeliveryOrderRecordResponse getDeliveryOrdersRecord(
            @RequestParam("deliveryOrderId") String deliveryOrderId
    ) {
        List<DeliveryRecordDTO> orderRecord = deliveryOrderService.getDeliveryOrderRecord(
                deliveryOrderId
        );
        DeliveryOrderRecordResponse response = new DeliveryOrderRecordResponse();
        response.setDeliveryRecords(orderRecord);
        return response;
    }

    /**
     * 撤销发货
     *
     * @param request 撤销发货请求
     * @return 撤销发货结果
     */
    @RequestMapping(value = "/orders/revoke", method = RequestMethod.PUT)
    @ResponseBody
    public DeliveryRevokeResponse revoke(
            @RequestBody DeliveryRevokeRequest request
    ) {
        deliveryOrderService.revoke(request.getDeliveryOrderId(),request.getUserId());
        DeliveryRevokeResponse response = new DeliveryRevokeResponse();
        return response;
    }

    @RequestMapping(value = "/edit/order/list", method = RequestMethod.GET)
    @ResponseBody
    public DeliverySaleOrdersResponse getEditSaleOrders(
            DeliverySaleOrdersRequest request
    ) {
        List<DeliverySaleOrderDTO> editSaleOrders = deliveryOrderService.getEditSaleOrders(
                request.getDeliveryOrderId(),
                request.getUnitId(),
                request.getCustomerId(),
                request.getStartSearchTime(),
                request.getStartTime(),
                request.getEndTime(),
                request.getType(),
                request.getSort());
        DeliverySaleOrdersResponse response = new DeliverySaleOrdersResponse();
        if (editSaleOrders!=null){
            response.setOrders(editSaleOrders);
        }else {
            response.setCode(500);
            response.setMessage("获取失败");


        }
        return response;
    }
}
